home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Commun⁄Network / Telnet 2.5.src.ThinkC / source / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-20  |  27.2 KB  |  1,190 lines  |  [TEXT/MPS ]

  1. /*
  2. *   Util.c
  3. *   utility library for use with the Network kernel
  4. *
  5. *   version 2, full session layer, TK started 6/17/87
  6. *
  7. ****************************************************************************
  8. *                                                                          *
  9. *      part of:                                                            *
  10. *      Network kernel for NCSA Telnet                                      *
  11. *      by Tim Krauskopf                                                    *
  12. *                                                                          *
  13. *      National Center for Supercomputing Applications                     *
  14. *      152 Computing Applications Building                                 *
  15. *      605 E. Springfield Ave.                                             *
  16. *      Champaign, IL  61820                                                *
  17. *                                                                          *
  18. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  19. *                                                                          *
  20. ****************************************************************************
  21. */
  22. #include <OSUtils.h>
  23. #include <stdio.h>
  24. #include "whatami.h"
  25. #include "hostform.h"
  26. #include "confile.h"
  27. #include "userd.h"
  28. #include "tools.h"
  29. #include "bkgr.h"
  30. #include "MacTCPCommonTypes.h"        /* BYU 2.4.8 */
  31. #include "AddressXlation.h"
  32.  
  33.  
  34. #ifdef MAC
  35. #include <String.h>
  36. #include <Memory.h>
  37. #include "macutil.h"
  38. #endif
  39.  
  40. #ifdef PC
  41. #include <string.h>
  42. #else
  43. #ifdef AZTEC
  44. #define strchr(A,B) index(A,B)
  45. #endif
  46. #endif
  47.  
  48. extern void putln(),userftpd();    /* BYU */
  49. char                             /* special function types */
  50.             *neterrstring();
  51. int32 time();                    /* don't forget this sucker! */
  52.  
  53. extern struct machinfo *Sns;
  54.  
  55. static unsigned char
  56.             *Ssstemps[] = {
  57.             (unsigned char *) "capfile",    /* BYU LSC */
  58.             (unsigned char *) "hp.out",        /* BYU LSC */
  59.             (unsigned char *) "ps.out",        /* BYU LSC */
  60.             (unsigned char *) "tek.out"        /* BYU LSC */
  61.             };
  62.  
  63. char Sptypes[NPORTS];        /* port types assigned for session use */
  64.  
  65. extern short slip_connection;    /* BYU 2.4.15 */
  66.  
  67. extern int EtherNet;            /* BYU 2.4.15 */
  68.  
  69. extern struct config Scon;        /* hardware configuration */
  70.  
  71. #define NTIMES 30
  72.  
  73. /*
  74. *  timer queue of events which will be placed into the event queue
  75. *  when the time is up.
  76. */
  77. struct {
  78.     unsigned char
  79.         eclass,                    /* event queue data */
  80.         event;
  81.     int
  82.         next,                    /* next item in list */
  83.         idata;
  84.     int32 when;                /* when timer is to go off */
  85. } Stq[NTIMES];
  86.  
  87.  
  88. struct DNRstruct {
  89.         struct machinfo *m;
  90.         Boolean done;
  91.         };
  92.  
  93. static int
  94.         domwait = 0,            /* is domain waiting for nameserver? */
  95.         Stfirst,Stfree;            /* pointers for timer queue */
  96.  
  97. #define PFTP 1
  98. #define PRCP 2
  99. #define PDATA 3
  100. #define PDOMAIN 4
  101.  
  102. /**************************************************************************/
  103. /*  Stask
  104. *   A higher level version of netsleep
  105. *
  106. *   This manages the timer queue
  107. */
  108.  
  109. static int32 recent=0L;
  110.  
  111. void Stask
  112.   (
  113.     void
  114.   )
  115.     {
  116.     long t;
  117.     int i;
  118.  
  119. /*#ifndef MacTCPdriver        /* BYU 2.4.16 - was "AppleDrivers" */
  120.     netsleep(0);
  121. /*#endif MacTCPdriver            /* BYU 2.4.16 */
  122.  
  123. /*
  124. *  Check the timer queue to see if something should be posted
  125. *  First check for timer wraparound
  126. */
  127.     t = time(NULL);
  128. #ifdef PC
  129.     if (t < recent) {
  130.         i = Stfirst;
  131.         while (i >= 0) {
  132.             Stq[i].when -= WRAPTIME;
  133.             i = Stq[i].next;
  134.         }
  135.     }
  136. #endif
  137.     recent = t;                            /* save most recent time */
  138.  
  139.     while (Stfirst >= 0 && t > Stq[Stfirst].when) {        
  140.                                 /* Q is not empty and timer is going off */
  141.         i = Stfirst;
  142.         netputevent(Stq[i].eclass,Stq[i].event,Stq[i].idata);
  143.         Stfirst = Stq[Stfirst].next;    /* remove from q */
  144.         Stq[i].next = Stfree;
  145.         Stfree = i;                        /* add to free list */
  146.     }
  147.  
  148.  
  149. }
  150.  
  151. /************************************************************************/
  152. /*  Snetinit
  153. *   Do network initialization for those who want the defaults all
  154. *   set for them.  Recommend that neterrchange be called before
  155. *   initializing network stuff.
  156. */
  157. int Snetinit
  158.   (
  159.     void
  160.   )
  161.     {
  162.     int i;
  163.  
  164. /*
  165. *  set up the file names
  166. */
  167.     Scon.capture = Ssstemps[0];
  168.     Scon.hpfile = Ssstemps[1];
  169.     Scon.psfile = Ssstemps[2];
  170.     Scon.tekfile = Ssstemps[3];
  171.  
  172.     neteventinit();                /* initializes for error messages to count */
  173.  
  174.     for (i=0; i<NPORTS; i++)
  175.         Sptypes[i] = -1;            /* clear port type flags */
  176.  
  177.     for (i=0; i<NTIMES; i++)
  178.         Stq[i].next = i+1;            /* load linked list */
  179.     Stq[NTIMES-1].next = -1;        /* anchor end */
  180.     Stfirst = -1;
  181.     Stfree = 0;
  182.  
  183.     if (!Sreadhosts()) {             /* parses config file */
  184. #ifdef PC
  185.         netparms(Scon.irqnum,Scon.address,Scon.ioaddr);
  186. #endif
  187.         netconfig((char *) Scon.hw);    /* BYU LSC */
  188.  
  189.         if (!netinit()) {            /* starts up hardware */
  190. /*
  191. *  Check for the need to RARP and do it
  192. */
  193.             netgetip(Scon.myipnum);    /* get stored ip num */
  194.             if (comparen(Scon.myipnum,(unsigned char *) "RARP",4)) {    /* BYU LSC - need RARP */
  195.                 if (netgetrarp())    /* stores in nnipnum at lower layer */
  196.                     return(-2);
  197.                 netgetip(Scon.myipnum);
  198.                 netsetip(Scon.myipnum);    
  199.             }
  200.  
  201. /*
  202. *  Give the lower layers a chance to check to see if anyone else
  203. *  is using the same ip number.  Usually generates an ARP packet.
  204. */
  205.             netarpme((char *) Scon.myipnum);        /* BYU LSC */
  206.  
  207.             Ssetgates();        /* BYU serial - moved to maclook.c, finishes IP inits */
  208.             Stask();
  209.             return(0);
  210.         }
  211.     }
  212.  
  213.     return(-1);    
  214. } /* Snetinit */
  215.  
  216. /**************************************************************************/
  217. /*  Stimerset
  218. *  Sets an asynchronous timer which is checked in Stask()
  219. *  usage:
  220. *  Time is in seconds
  221. *  Stimerset(class,event,dat,time)
  222. *    int class,event,dat,time;
  223. *    class,event,dat is the event which should be posted at the specified
  224. *    time.  Accuracy is dependent on how often Stask is called.
  225. */
  226.  
  227. int Stimerset
  228.   (
  229.     int class,
  230.     int event,
  231.     int dat,
  232.     int howlong
  233.   )
  234.     {
  235.     int i,j,jlast,retval;
  236.     int32 gooff;
  237.  
  238.     retval = 0;
  239.     gooff = time(NULL) + howlong;
  240.  
  241.     if (Stfree < 0) {                /* queue is full, post first event */
  242.         Stfree = Stfirst;
  243.         Stfirst = Stq[Stfirst].next;
  244.         Stq[Stfree].next = -1;
  245.         netputevent(Stq[Stfree].eclass,Stq[Stfree].event,Stq[Stfree].idata);
  246.         retval = -1;
  247.     }
  248.  
  249.     Stq[Stfree].idata = dat;                /* event to occur at that time */
  250.     Stq[Stfree].event = event;
  251.     Stq[Stfree].eclass = class;
  252.     Stq[Stfree].when = gooff;
  253.     i = Stfree;                            /* remove from free list */
  254.     Stfree = Stq[i].next;
  255.  
  256.     if (Stfirst < 0) {                    /* if no queue yet */
  257.         Stfirst = i;
  258.         Stq[i].next = -1;                /* anchor active q */
  259.     }
  260.  
  261.     else if (gooff < Stq[Stfirst].when) {    /* goes first on list */
  262.         Stq[i].next = Stfirst;                /* at beginning of list */
  263.         Stfirst = i;
  264.     }
  265.  
  266.     else {                                    /* goes in middle */
  267.  
  268.         j = jlast = Stfirst;                /* search q from beginning */
  269.  
  270.         while (gooff >= Stq[j].when && j >= 0) {
  271.             jlast = j;
  272.             j = Stq[j].next;
  273.         }
  274.         Stq[i].next = j;                    /* insert in q */
  275.         Stq[jlast].next = i;
  276.     }
  277.  
  278.     return(retval);
  279. }
  280.  
  281. /**************************************************************************/
  282. /*  Snetopen
  283. *
  284. *   Takes a pointer to a machine record, looked up with Sgethost and
  285. *   initiates the TCP open call.
  286. *
  287. */
  288. int Snetopen
  289.   (
  290.     struct machinfo *m,
  291.     int tport,                /* BYU 2.4.15 */
  292.     short connectionType    /* BYU 2.4.15 */
  293.   )
  294.     {
  295.     int j;
  296.  
  297.     if ((connectionType == 0) && (EtherNet == -100)) {        /* BYU 2.4.15 */
  298.         OtherError((char *) "\pError opening network port.",(char *) "\pNetwork was not initialized.");        /* BYU 2.4.15 */
  299.         return -1;                                            /* BYU 2.4.15 */
  300.     }                                                        /* BYU 2.4.15 */
  301.  
  302.     if (!connectionType && (!m || m->mstat < HAVEIP))        /* BYU 2.4.15 */
  303.         return(-1);
  304.  
  305. #if 1                                /* BYU 2.4.15 */
  306.     j = netxopen((uint32 *) m->hostip,tport,m->retrans,m->mtu,m->maxseg,m->window,connectionType);
  307. #else                                /* BYU 2.4.15 */
  308.     j = netxopen((uint32 *) m->hostip,tport,m->retrans,m->mtu,m->maxseg,m->window);
  309.                                     /* do the open call */
  310. #endif                                /* BYU 2.4.15 */
  311.  
  312.     if (j >= 0) {
  313.         Sptypes[j] = -1;            /* is allocated to user */
  314.         if ((connectionType == 0) || slip_connection) {                /* BYU 2.4.15 */
  315.             Stimerset(CONCLASS,CONFAIL,j,m->conto);                    /* BYU 2.4.15 */
  316.             Stimerset(SCLASS,RETRYCON,j,m->retrans/TICKSPERSEC+2);    /* BYU 2.4.15 */
  317.         }                                                            /* BYU 2.4.15 */
  318.     }
  319.  
  320.     return(j);
  321. }
  322.  
  323.  
  324. /**************************************************************************/
  325. /*
  326. *  special domain data structures
  327. */
  328. #define DOMSIZE 512                /* maximum domain message size to mess with */
  329.  
  330. /*
  331. *  Header for the DOMAIN queries
  332. *  ALL OF THESE ARE BYTE SWAPPED QUANTITIES!
  333. *  We are the poor slobs who are incompatible with the world's byte order
  334. */
  335. struct dhead {
  336. uint16
  337.     ident,                /* unique identifier */
  338.     flags,    
  339.     qdcount,            /* question section, # of entries */
  340.     ancount,            /* answers, how many */
  341.     nscount,            /* count of name server RRs */
  342.     arcount;            /* number of "additional" records */
  343. };
  344.  
  345. /*
  346. *  flag masks for the flags field of the DOMAIN header
  347. */
  348. #define DQR        0x8000            /* query = 0, response = 1 */
  349. #define DOPCODE    0x7100            /* opcode, see below */
  350. #define DAA        0x0400            /* Authoritative answer */
  351. #define DTC        0x0200            /* Truncation, response was cut off at 512 */
  352. #define DRD        0x0100            /* Recursion desired */
  353. #define DRA        0x0080            /* Recursion available */
  354. #define DRCODE    0x000F            /* response code, see below */
  355.  
  356.                                 /* opcode possible values: */
  357. #define DOPQUERY    0            /* a standard query */
  358. #define DOPIQ        1            /* an inverse query */
  359. #define DOPCQM        2            /* a completion query, multiple reply */
  360. #define DOPCQU        3             /* a completion query, single reply */
  361. /* the rest reserved for future */
  362.  
  363.                                 /* legal response codes: */
  364. #define DROK    0                /* okay response */
  365. #define DRFORM    1                /* format error */
  366. #define DRFAIL    2                /* their problem, server failed */
  367. #define DRNAME    3                /* name error, we know name doesn't exist */
  368. #define DRNOPE    4                /* no can do request */
  369. #define DRNOWAY    5                /* name server refusing to do request */
  370.  
  371. #define DTYPEA    1                /* host address resource record (RR) */
  372. #define DTYPEPTR    12            /* a domain name ptr */
  373.  
  374. #define DIN        1                /* ARPA internet class */
  375. #define DWILD    255                /* wildcard for several of the classifications */
  376.  
  377. /*
  378. *  a resource record is made up of a compressed domain name followed by
  379. *  this structure.  All of these ints need to be byteswapped before use.
  380. */
  381. struct rrpart {
  382.     uint16
  383.         rtype,                    /* resource record type = DTYPEA */
  384.         rclass;                    /* RR class = DIN */
  385.     uint32
  386.         rttl;                    /* time-to-live, changed to 32 bits */
  387.     uint16
  388.         rdlength;                /* length of next field */
  389.     uint8
  390.         rdata[DOMSIZE];            /* data field */
  391. };
  392.  
  393. /*
  394. *  data for domain name lookup
  395. */
  396. struct useek {
  397.     struct dhead h;
  398.     uint8 x[DOMSIZE];
  399. } question;
  400.  
  401. qinit()
  402.     {
  403.     question.h.flags = intswap(DRD);
  404.     question.h.qdcount = intswap(1);
  405.     question.h.ancount = 0;
  406.     question.h.nscount = 0;
  407.     question.h.arcount = 0;
  408. }
  409.  
  410.  
  411. /*********************************************************************/
  412. /*  packdom
  413. *   pack a regular text string into a packed domain name, suitable
  414. *   for the name server.
  415. */
  416. packdom(dst,src)
  417.     char *src,*dst;
  418.     {
  419.     char *p,*q,*savedst;
  420.     int i,dotflag,defflag;
  421.  
  422.     p = src;
  423.     dotflag = defflag = 0;
  424.     savedst = dst;
  425.  
  426.     do {                            /* copy whole string */
  427.         *dst = 0;
  428.         q = dst + 1;
  429.  
  430. /*
  431. *  copy the next label along, char by char until it meets a period or
  432. *  end of string.
  433. */
  434.         while (*p && (*p != '.')) 
  435.             *q++ = *p++;
  436.  
  437.         i = p - src;
  438.         if (i > 0x3f)
  439.             return(-1);
  440.         *dst = i;
  441.         *q = 0;
  442.  
  443.         if (*p) {                    /* update pointers */
  444.             dotflag = 1;
  445.             src = ++p;
  446.             dst = q;
  447.         }
  448.         else if (!dotflag && !defflag && Scon.defdom) {
  449.             p = (char *) Scon.defdom;        /* BYU LSC - continue packing with default */
  450.             defflag = 1;
  451.             src = p;
  452.             dst = q;
  453.             netposterr(801);        /* using default domain */
  454.         }
  455.  
  456.     } while (*p);
  457.  
  458.     q++;
  459.     return(q-savedst);            /* length of packed string */
  460. }
  461.  
  462. /*********************************************************************/
  463. /*  unpackdom
  464. *  Unpack a compressed domain name that we have received from another
  465. *  host.  Handles pointers to continuation domain names -- buf is used
  466. *  as the base for the offset of any pointer which is present.
  467. *  returns the number of bytes at src which should be skipped over.
  468. *  Includes the NULL terminator in its length count.
  469. */
  470. unpackdom(dst,src,buf)
  471.     char *src,*dst,buf[];
  472.     {
  473.     int i,j,retval;
  474.     char *savesrc;
  475.  
  476.     savesrc = src;
  477.     retval = 0;
  478.  
  479.     while (*src) {
  480.         j = *src;
  481.  
  482.         while ((j & 0xC0) == 0xC0) {
  483.             if (!retval)
  484.                 retval = src-savesrc+2;
  485.             src++;
  486.             src = &buf[(j & 0x3f)*256+*src];        /* pointer dereference */
  487.             j = *src;
  488.         }
  489.  
  490.         src++;
  491.         for (i=0; i < (j & 0x3f) ; i++)
  492.             *dst++ = *src++;
  493.  
  494.         *dst++ = '.';
  495.     }
  496.  
  497.     *(--dst) = 0;            /* add terminator */
  498.     src++;                    /* account for terminator on src */
  499.  
  500.     if (!retval)
  501.         retval = src-savesrc;
  502.  
  503.     return(retval);
  504. }
  505.  
  506. /*********************************************************************/
  507. /*  sendom
  508. *   put together a domain lookup packet and send it
  509. *   uses port 53
  510. */
  511. sendom(s,towho,num)
  512.     char *s,*towho;
  513.     int16 num;
  514.     {
  515.     uint16 i,ulen;
  516.     uint8 *psave,*p;
  517.  
  518.     psave = (uint8 *)question.x;
  519.  
  520.     i = packdom((char *) question.x,s);        /* BYU LSC */
  521.  
  522. /*
  523. *  load the fields of the question structure a character at a time so
  524. *  that 68000 machines won't barf.
  525. */
  526.     p = &question.x[i];
  527.     *p++ = 0;                /* high byte of qtype */
  528.     *p++ = DTYPEA;            /* number is < 256, so we know high byte=0 */
  529.     *p++ = 0;                /* high byte of qclass */
  530.     *p++ = DIN;                /* qtype is < 256 */
  531.  
  532.     question.h.ident = intswap(num);
  533.     ulen = sizeof(struct dhead)+(p-psave);
  534.  
  535.     netusend((unsigned char *) towho, 53, 997, (unsigned char *) &question, ulen);    /* BYU LSC */
  536.     
  537. }
  538.  
  539.  
  540. pascal void DNRDone(hostInfoPtr,DNR)
  541. struct hostInfo *hostInfoPtr;
  542. struct DNRstruct *DNR;
  543. {
  544.     DNR->m->mstat = HAVEIP; 
  545. /*    putln("got to DNRdone");            /* BYU LSC - not needed */
  546.     if (!hostInfoPtr->rtnCode)            /* no error, so open it up */
  547.     {
  548.         memmove(DNR->m->hostip,hostInfoPtr->addr,4);    /* BYU LSC - was "movebytes" */
  549.         netputevent(USERCLASS,DOMOK,DNR->m->mno);
  550.     }
  551.     else
  552.         netputevent(USERCLASS,DOMFAIL,DNR->m->mno); /* cant find ip # */
  553.     DNR->done = -1;                    /* BYU LSC - was "true" */
  554.     DisposPtr((char *)DNR);
  555.     DisposPtr((char *)hostInfoPtr);
  556. /*    putln("got past DNRdone");            /* BYU LSC - not needed */
  557.  
  558. }
  559.  
  560.  
  561.  
  562.  
  563. /**************************************************************************/
  564. /*  Sdomain
  565. *   DOMAIN based name lookup
  566. *   query a domain name server to get an IP number
  567. *    Returns the machine number of the machine record for future reference.
  568. *   Events generated will have this number tagged with them.
  569. *   Returns various negative numbers on error conditions.
  570. */
  571. int Sdomain
  572.   (
  573.     char *mname
  574.   )
  575. {
  576. struct machinfo    *m;
  577.  
  578. /*#ifdef MacTCPdriver                    /* BYU 2.4.16 */
  579. OSErr            theError;
  580. struct hostInfo    *myHost;
  581. Boolean            done;
  582. int                i;
  583. struct DNRstruct *DNRstuff;
  584. /*#endif                                /* BYU 2.4.16 */
  585.  
  586. /*#ifndef MacTCPdriver                    /* BYU - was NEW_STUFF */
  587.     if (!Sns && EtherNet != -99)         /* BYU 2.4.16 - no nameserver, give up now */
  588.         return(-1);
  589. /*#endif                                /* BYU 2.4.16 */
  590.  
  591.     while (*mname && *mname < 33)        /* kill leading spaces */
  592.         mname++;
  593.     if (!(*mname))
  594.         return(-1);
  595.  
  596.     if (!(m = Smadd(mname)))
  597.         return(-1);                        /* adds the number to the machlist */
  598.  
  599.     if (domwait < Scon.domto)
  600.         domwait = Scon.domto;            /* set the minimum timeout */
  601.     
  602. /*#ifdef MacTCPdriver                    /* BYU 2.4.16 - was NEW_STUFF */
  603.  
  604.     if (EtherNet == -99) {                /* BYU 2.4.16 */
  605.  
  606.         DNRstuff = (struct DNRstruct *) NewPtr(sizeof(struct DNRstruct));
  607.         myHost = (struct hostInfo *) NewPtr(sizeof(struct hostInfo)*2);
  608.  
  609. #if 0                                                /* BYU LSC - not needed */
  610.         putln("Going to try to get domain name");    
  611.         putln("\015");                                /* BYU 2.4.18 - changed \n to \015 */
  612. #endif                                                /* BYU LSC - not needed */
  613.  
  614.         for (i = 0; i < NUM_ALT_ADDRS; i++)
  615.             myHost->addr[i] = 0;
  616.         done = false;
  617.         if (!m->hname) m->hname = m->sname;        /* BYU - patch received from Scott@NCSA. */
  618.         DNRstuff->m = m;
  619.         DNRstuff->done = done;
  620. /*        c2pstr((char *) m->hname);                /* BYU LSC */
  621.         theError = StrToAddr((char *) m->hname,myHost,(ResultProcPtr) DNRDone,(Ptr)DNRstuff);    /* BYU LSC */
  622. /*        p2cstr((char *) m->hname);                /* BYU LSC */
  623.     
  624.         if (theError != cacheFault) DNRDone(myHost,DNRstuff);
  625.         m->mstat = HAVEIP;
  626. /*#else                                        /* BYU 2.4.16 */
  627.  
  628.     } else {                                /* BYU 2.4.16 */
  629.  
  630.         qinit();                            /* initialize some flag fields */
  631.         netulisten(997);                    /* pick a return port */
  632.         if (!m->hname)
  633.             m->hname = m->sname;            /* copy pointer to sname */
  634.         sendom((char *) m->hname,(char *) Sns->hostip,m->mno);    /* BYU LSC - try UDP */
  635.         Stimerset(SCLASS,UDPTO,m->mno,domwait);    /* time out quickly first time */
  636.         m->mstat = UDPDOM;
  637. /*#endif                                    /* BYU 2.4.16 */
  638.  
  639.     }                                        /* BYU 2.4.16 */
  640.  
  641.     return(m->mno);
  642.   }
  643.  
  644. /*********************************************************************/
  645. /*  ddextract
  646. *   extract the ip number from a response message.
  647. *   returns the appropriate status code and if the ip number is available,
  648. *   copies it into mip
  649. */
  650. int ddextract
  651.   (
  652.     struct useek *qp,
  653.     unsigned char *mip
  654.   )
  655. {
  656. uint16 i,j,nans,rcode;
  657. struct rrpart *rrp;
  658. uint8 *p,space[260];
  659.  
  660.     nans = intswap(qp->h.ancount);                /* number of answers */
  661.     rcode = DRCODE & intswap(qp->h.flags);        /* return code for this message*/
  662.     if (rcode > 0)
  663.         return(rcode);
  664.  
  665.     if (nans > 0 &&                                /* at least one answer */
  666.         (intswap(qp->h.flags) & DQR)) {            /* response flag is set */
  667.         p = (uint8 *)qp->x;                    /* where question starts */
  668.         i = unpackdom((char *) space,(char *) p,(char *) qp);    /* BYU LSC - unpack question name */
  669. /*  spec defines name then  QTYPE + QCLASS = 4 bytes */
  670.         p += i+4;
  671. /*
  672. *  at this point, there may be several answers.  We will take the first
  673. *  one which has an IP number.  There may be other types of answers that
  674. *  we want to support later.
  675. */
  676.         while (nans-- > 0) {                    /* look at each answer */
  677.             i = unpackdom((char *) space,(char *) p,(char *) qp);    /* BYU LSC - answer name to unpack */
  678. /*            n_puts(space);*/
  679.             p += i;                                /* account for string */
  680.             rrp = (struct rrpart *)p;            /* resource record here */
  681. /*
  682. *  check things which might not align on 68000 chip one byte at a time
  683. */
  684.             if (!*p && *(p+1) == DTYPEA &&         /* correct type and class */
  685.                 !*(p+2) && *(p+3) == DIN) {
  686.                 memmove((void *) mip,rrp->rdata,4);    /* BYU LSC - save IP # */
  687.                 return(0);                        /* successful return */
  688.             }
  689.             memmove((void *) &j,(void *) &rrp->rdlength,2);        /* BYU LSC - 68000 alignment */
  690.             p += 10+intswap(j);                    /* length of rest of RR */
  691.         }
  692.     }
  693.  
  694.     return(-1);                        /* generic failed to parse */
  695. }
  696.  
  697. /****************************************************************************/
  698. /*  Stimerunset
  699. *   Remove all such timer events from the queue
  700. *   They must match all three fields, event, class and optional data
  701. *
  702. */
  703. int Stimerunset
  704.   (
  705.     unsigned char class,
  706.     unsigned char event,
  707.     int dat
  708.   )
  709. {
  710. int i,ilast,retval;
  711.  
  712.     retval = ilast = -1;
  713.     i = Stfirst;
  714.     while (i >= 0 ) {                    /* search list */
  715.  
  716.         if (Stq[i].idata == dat &&         /* this one matches */
  717.             Stq[i].eclass == class && Stq[i].event == event) {
  718.  
  719.             retval = 0;                    /* found at least one */
  720. /*
  721. * major bug fix -- if first element matched, old code could crash
  722. */
  723.             if (i == Stfirst) {
  724.                 Stfirst = Stq[i].next;            /* first one matches */
  725.                 Stq[i].next = Stfree;            /* attach to free list */
  726.                 Stfree = i;
  727.                 i = Stfirst;
  728.                 continue;                        /* start list over */
  729.             }
  730.             else {
  731.                 Stq[ilast].next = Stq[i].next;    /* remove this entry */
  732.                 Stq[i].next = Stfree;            /* attach to free list */
  733.                 Stfree = i;
  734.                 i = ilast;
  735.             }
  736.         }
  737.  
  738.         ilast = i;
  739.         i = Stq[i].next;
  740.     }
  741.  
  742.     return(retval);
  743. }
  744.  
  745. /*********************************************************************/
  746. /*  getdomain
  747. *   Look at the results to see if our DOMAIN request is ready.
  748. *   It may be a timeout, which requires another query.
  749. */
  750.  
  751. udpdom()
  752. {
  753. struct machinfo    *m;
  754. int                i,uret,num;
  755. char            *p;
  756.  
  757.     uret = neturead((char *) &question);
  758.  
  759.     if (uret < 0)
  760.     {
  761. /*        netputevent(USERCLASS,DOMFAIL,-1);  */
  762.         return(-1);
  763.     }
  764.  
  765.     num = intswap(question.h.ident);        /* get machine number */
  766. /*
  767. *  check to see if the necessary information was in the UDP response
  768. */
  769.     m = Slooknum(num);                /* get machine info record */
  770.     if (!m)
  771.     {
  772.         netputevent(USERCLASS,DOMFAIL,num);
  773.         return(-1);
  774.     }
  775.  
  776. /*
  777. *  got a response, so reset timeout value to recommended minimum
  778. */
  779.     domwait = Scon.domto;
  780.  
  781.     i = ddextract(&question,m->hostip);
  782.  
  783.     switch (i) {
  784.         case 3:                        /* name does not exist */
  785.             netposterr(802);
  786.             p = neterrstring(-1);
  787.             strncpy(p,(char *) m->hname,78);    /* BYU LSC - what name */
  788.             netposterr(-1);
  789.             netputevent(USERCLASS,DOMFAIL,num);
  790.             Stimerunset(SCLASS,UDPTO,num);
  791.             return(-1);
  792.         case 0:                        /* we found the IP number */
  793.             Stimerunset(SCLASS,UDPTO,num);
  794.             m->mstat = DOM;            /* mark that we have it from DOMAIN */
  795.             netputevent(USERCLASS,DOMOK,num);
  796.             return(0);
  797.         case -1:                    /* strange return code from ddextract */
  798.             netposterr(803);
  799.             break;
  800.         default:
  801.             netposterr(804);
  802.             break;
  803.     }
  804.  
  805.     return(0);
  806.  
  807. }
  808.  
  809. /**************************************************************************/
  810. /*  domto
  811. *   Handle time out for DOMAIN name lookup
  812. *   Retry as many times as recommended by config file
  813. */
  814. domto(num)
  815. int num;
  816. {
  817. struct machinfo *m;
  818.  
  819.     m = Slooknum(num);
  820.     if (!m)
  821.         return(-1);
  822.  
  823.     if (m->mstat > UDPDOM + Scon.ndom) {    /* permanent timeout */
  824.         netputevent(USERCLASS,DOMFAIL,num);
  825.         return(-1);
  826.     }
  827.     else
  828.         m->mstat++;            /* one more timeout */
  829.     
  830.     if (domwait < 20)        /* exponential backoff */
  831.         domwait <<= 1;
  832.  
  833.     Snewns();                /* rotate to next nameserver */
  834.  
  835.     qinit();
  836.  
  837.     netulisten(997);                    /* pick a return port */
  838.     sendom((char *) m->hname,(char *) Sns->hostip,num);        /* BYU LSC - try UDP */
  839.  
  840.     Stimerset(SCLASS,UDPTO,num,domwait);    /* time out more slowly */
  841.  
  842.     return(num);
  843.     
  844. }
  845.  
  846.  
  847. /***********************************************************************/
  848. static int son=1;
  849.  
  850. Scwritemode(mode)
  851. int mode;
  852. {
  853.     son = mode;
  854.     return(0);
  855. }
  856.  
  857. /***********************************************************************/
  858. Scmode()
  859. {
  860.     return(son);
  861. }
  862.  
  863. /***********************************************************************/
  864. static int tekon=1;
  865.  
  866. void Stekmode
  867.   (
  868.     int mode
  869.   )
  870. /*int mode;            /* BYU LSC */
  871. {
  872.         tekon = mode;
  873. }
  874.  
  875. /***********************************************************************/
  876. Stmode()
  877. {
  878.     return(tekon);
  879. }
  880.  
  881. /***********************************************************************/
  882. #ifdef PC
  883. static int rcpon=1;
  884.  
  885. Srcpmode(mode)
  886. int mode;
  887. {
  888.     rcpon = mode;
  889.     if (rcpon)
  890.         setrshd();
  891.     else
  892.         unsetrshd();
  893.     return(0);
  894. }
  895.  
  896. /***********************************************************************/
  897. Srmode()
  898. {
  899.     return(rcpon);
  900. }
  901. #endif
  902.  
  903. /***********************************************************************/
  904. static int ftpon=0;
  905.  
  906. int Sftpmode
  907.   (
  908.     int mode
  909.   )
  910. {
  911.     if (ftpon && mode)
  912.         return(-1);
  913.  
  914.     ftpon = mode;
  915.     if (ftpon)
  916.         setftp();
  917.     else
  918.         unsetftp();
  919.     return(0);
  920. }
  921.  
  922. /***********************************************************************/
  923. int Sfmode
  924.   (
  925.     void
  926.   )
  927. {
  928.     return(ftpon);
  929. }
  930.  
  931. /***********************************************************************/
  932. /*  Snewcap
  933. *   set a new capture file name
  934. */
  935. int Snewcap
  936.   (
  937.     char *s
  938.   )
  939. {
  940.     if (NULL == (Scon.capture = (unsigned char *) NewPtr(strlen(s)+1)))    /* BYU LSC */
  941.         return(1);
  942.     strcpy((char *) Scon.capture,s);    /* BYU LSC */
  943.     return(0);
  944. }
  945.  
  946. /***********************************************************************/
  947. /*  Snewps
  948. *   set a new ps file name
  949. */
  950. int Snewpsfile
  951.   (
  952.     char *s
  953.   )
  954. {
  955.     if (NULL == (Scon.psfile = (unsigned char *) NewPtr(strlen(s)+1)))    /* BYU LSC */
  956.         return(1);
  957.     strcpy((char *) Scon.psfile,s);        /* BYU LSC */
  958.     return(0);
  959. }
  960.  
  961. /***********************************************************************/
  962. /*  Snewhpfile
  963. *   set a new HPGL file name
  964. */
  965. int Snewhpfile
  966.   (
  967.     char *s
  968.   )
  969. {
  970.     if (NULL == (Scon.hpfile = (unsigned char *) NewPtr(strlen(s)+1)))    /* BYU LSC */
  971.         return(1);
  972.     strcpy((char *) Scon.hpfile,s);        /* BYU LSC */
  973.     return(0);
  974. }
  975.  
  976. /***********************************************************************/
  977. /*  Snewtekfile
  978. *   set a new tek file name
  979. */
  980. int Snewtekfile
  981.   (
  982.     char *s
  983.   )
  984. {
  985.     if (NULL == (Scon.tekfile = (unsigned char *) NewPtr(strlen(s)+1)))    /* BYU LSC */
  986.         return(1);
  987.     strcpy((char *) Scon.tekfile,s);        /* BYU LSC */
  988.     return(0);
  989. }
  990.  
  991. /***********************************************************************/
  992. /*  Sopencap
  993. *   returns a file handle to an open capture file
  994. *   Uses the locally stored capture file name.
  995. */
  996. FILE *
  997. Sopencap()
  998. {
  999. FILE *retfp;
  1000.  
  1001.     if (NULL == (retfp = fopen((char *) Scon.capture,"ab")))     /* BYU LSC */
  1002.         return(NULL);
  1003.  
  1004.     fseek(retfp,0L,2);        /* seek to end */
  1005.  
  1006.     return(retfp);
  1007. }
  1008.  
  1009. /****************************************************************************/
  1010. /* Scompass
  1011. *  compute and check the encrypted password
  1012. */
  1013. int Scompass
  1014.   (
  1015.     char *ps,
  1016.     char *en
  1017.   )
  1018. {
  1019. int ck;
  1020. char *p,c;
  1021.  
  1022.     ck = 0;
  1023.     p = ps;
  1024.     while (*p)                /* checksum the string */
  1025.         ck += *p++;
  1026.  
  1027.     c = ck;
  1028.  
  1029.     while (*en) {
  1030.         if ((((*ps ^ c) | 32) & 127) != *en)    /* XOR with checksum */
  1031.             return(0);
  1032.         if (*ps)
  1033.             ps++;
  1034.         else
  1035.             c++;            /* increment checksum to hide length */
  1036.         en++;
  1037.     }
  1038.  
  1039.     return(1);
  1040. }
  1041.  
  1042. /****************************************************************************/
  1043. /*  Scheckpass
  1044. *   Check the password file for the user,password combination
  1045. *   Returns valid or invalid
  1046. */
  1047. int Scheckpass
  1048.   (
  1049.     char *us,
  1050.     char *ps
  1051.   )
  1052. /*char *us,*ps;        /* BYU LSC */
  1053. {
  1054. char buf[81],*p;
  1055. FILE *fp;
  1056.  
  1057.     if (NULL == (fp = fopen((char *) Scon.pass,"r"))) {        /* BYU LSC */
  1058.     
  1059. #ifdef MAC
  1060. /*
  1061. *  failed open, so try to find file in the system folder.
  1062. */
  1063.  
  1064.         sysdir();                            /* change to system folder */
  1065.         fp = fopen((char *) Scon.pass,"r");    /* BYU LSC */
  1066.         
  1067.         setmydir();                            /* reset back to default dir */
  1068.         
  1069.         if (NULL == fp)                        /* still didn't work? */
  1070. #endif
  1071.             return(0);
  1072.     }
  1073.  
  1074.     while (NULL != fgets(buf,80,fp)) {
  1075.         p = strchr(buf,'\012');    /* BYU 2.4.18 - changed \n to \015 */ /* BYU 2.4.19 - changed to \012 */
  1076.         *p = '\0';                            /* remove \n */
  1077.  
  1078.         p = strchr(buf,':');                /* find delimiter */
  1079.         *p++ = '\0';
  1080.         if (!strcmp(buf,us) &&            /* found user */
  1081.             Scompass(ps,p)) {            /* does password check ?*/
  1082.             fclose(fp);
  1083.             return(1);
  1084.         }
  1085.     }
  1086.  
  1087.     fclose(fp);
  1088.     return(0);
  1089. }
  1090.  
  1091. /****************************************************************************/
  1092. /* Sneedpass
  1093. *  For other routines to call and find out if a password is required
  1094. */
  1095. int Sneedpass
  1096.   (
  1097.     void
  1098.   )
  1099. {
  1100.     if (Scon.pass == NULL)
  1101.         return(0);
  1102.  
  1103.     return(1);
  1104. }
  1105.  
  1106. /****************************************************************************/
  1107. /*  Sgetevent
  1108. *   gets events from the network and filters those for session related
  1109. *   activity.  Returns any other events to the caller.
  1110. */
  1111. int Sgetevent
  1112.   (
  1113.     int class,
  1114.     int *what,
  1115.     int *datp
  1116.   )
  1117. {
  1118. int retval;
  1119.  
  1120.     if (retval = netgetevent(SCLASS,what,datp)) {    /* session event */
  1121.         switch (retval) {
  1122.             case FTPACT:
  1123.                 ftpd(0,*datp);
  1124.                 break;
  1125. #ifdef PC
  1126.             case RCPACT:                /* give CPU to rsh for rcp */
  1127.                 rshd(0);
  1128.                 break;
  1129. #endif
  1130. #ifdef MAC
  1131.             case CLOSEDONE:                /* Used in the drivers */
  1132.                 netclose( *datp);
  1133.                 break;
  1134.             case CLOSEDONE+1:                /* Used in the drivers */
  1135.                 netclose( *datp);
  1136.                 break;
  1137. #endif MAC
  1138.             case UDPTO:                    /* name server not responding */
  1139.                 domto(*datp);
  1140.                 break;
  1141.             case RETRYCON:
  1142.                 if (0 < netopen2(*datp))     /* connection open yet? */
  1143.                     Stimerset(SCLASS,RETRYCON,*datp,4);  /* 4 is a kludge */
  1144.                 break;
  1145.  
  1146.             default:
  1147.                 break;
  1148.         }
  1149.     }
  1150.  
  1151.     Stask();                        /* allow net and timers to take place */
  1152.  
  1153.     if (!(retval = netgetevent(class,what,datp)))
  1154.         return(0);
  1155.         
  1156.     if (retval == CONOPEN) 
  1157.         Stimerunset(CONCLASS,CONFAIL,*datp);   /* kill this timer */
  1158.  
  1159.     if ((*datp == 997) && (retval == UDPDATA)) {
  1160.         udpdom();
  1161.     }
  1162.     else if ((*what == CONCLASS) && (Sptypes[*datp] >= 0)) {
  1163.                                         /* might be for session layer */
  1164.         switch (Sptypes[*datp]) {
  1165.             case PFTP:
  1166.                 rftpd(retval,*datp);        /* BYU 2.4.16 */
  1167.                 break;
  1168.             case PDATA:
  1169.                 ftpd(retval,*datp);
  1170.                 break;
  1171.             case UDATA:                        /* BYU */
  1172.                 userftpd(retval,*datp);        /* BYU */
  1173.                 break;                        /* BYU */
  1174. #ifdef PC
  1175.             case PRCP:
  1176.                 rshd(retval);
  1177.                 break;
  1178. #endif
  1179.             default:
  1180.                 break;
  1181.         }
  1182.     }
  1183.     else
  1184.         return(retval);                /* let higher layer have it */
  1185.  
  1186.     return(0);
  1187. }
  1188.  
  1189.  
  1190.